import abc

'''飞行为的接口类'''


class FlyBehavior(abc.ABC, object):

    @abc.abstractmethod
    def fly(self):
        pass


'''叫行为的接口类'''


class QuackBehavior(abc.ABC, object):

    @abc.abstractmethod
    def quack(self):
        pass


'''鸭子的抽象基类'''


class Duck(abc.ABC, object):
        # 存放可以明确分类方法的指针
    def __init__(self, p_FlyBehevior: FlyBehavior, p_QuackBehavior: QuackBehavior):
        self.p_FlyBehevior = p_FlyBehevior
        self.p_QuackBehavior = p_QuackBehavior

        # 可以明确分类方法
    def perform_fly(self):
        self.p_FlyBehevior.fly()

    def perform_quack(self):
        self.p_QuackBehavior.quack()

        # 不可明确分类的方法
    @abc.abstractmethod
    def display(self):
        pass

        # 公共代码
    def swim(self):
        print("我在游泳呢！！！")

    '''实现类'''


'''实现飞行行为的方法类'''


class FlyWithWings(FlyBehavior):

    def fly(self):
        print("带着翅膀飞")


class FlyNoWay(FlyBehavior):
    def fly(self):
        print("我是一只不会分的鸭子")


'''实现叫行为的方法类'''


class Quack(QuackBehavior):
    def quack(self):
        print("嘎嘎叫")


class MuteQuack(QuackBehavior):
    def quack(self):
        print("不会叫")


class SqueakQuack(QuackBehavior):
    def quack(self):
        print("吱吱叫")

    '''真实的鸭类实现类'''
# 绿头鸭类


class MallardDuck(Duck):
    # 绿头鸭默认可以飞，普通的嘎嘎叫
    def __init__(self, p_FlyBehevior=FlyWithWings, p_QuackBehavior=Quack()):
        Duck.__init__(self, FlyWithWings(), Quack())

    def display(self):
        print("我是一只绿头鸭")
        # 可明确分类策略模式的关键
        self.perform_fly()  # 执行飞
        self.perform_quack()  # 执行叫
        # 公共代码
        self.swim()  # 执行游泳


if __name__ == "__main__":
    md = MallardDuck()
    md.display()
    md.perform_fly()
    md.perform_quack()
    md.swim()
